package ws.jonas.sybosc;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.sql.SQLException;

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;

import ws.jonas.sybosc.db.DBConnection;
import ws.jonas.sybosc.db.DBConfig;
import ws.jonas.sybosc.gui.ConfigDialog;
import ws.jonas.sybosc.gui.LogPanel;
import ws.jonas.sybosc.gui.StatusBarPanel;
import ws.jonas.sybosc.gui.SyboscPanel;

/**
 * TODO: grep -r 'TODO' *
 */
public class Sybosc {
	private final JFrame mainFrame;
	private final JMenu mainMenu;
	private final JMenuBar menuBar;
	private final JMenuItem configMenuItem;
	private final JMenuItem connectMenuItem;
	private final JMenuItem disconnectMenuItem;
	private final JMenuItem exitMenuItem;
	private final JPanel mainPane;
	private final SyboscPanel syboscPane;
	private final LogPanel logPane;
	private final StatusBarPanel statusBarPane;
	private final JTabbedPane tabbedPane;
	private final DBConfig config = new DBConfig();
	private final DBConnection conn;

	public Sybosc() {
		conn = new DBConnection(new DBConnection.ConnectionCallback() {
			@Override
			public void onConnect() {
				syboscPane.onConnect();
				statusBarPane.onConnect();
			}

			@Override
			public void onDisconnect() {
				syboscPane.onDisconnect();
				statusBarPane.onDisconnect();
			}
		});

		syboscPane = new SyboscPanel(conn);
		logPane = LogPanel.getInstance();
		statusBarPane = new StatusBarPanel();
		LogPanel.setStatusBar(statusBarPane);

		mainFrame = new JFrame("Sybosc");

		connectMenuItem = new JMenuItem("Connect", KeyEvent.VK_C);
		connectMenuItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				try {
					if (!conn.isOnline()) {
						conn.connect(config);
						logPane.println("Connected to " + config.getHost());
					}
				} catch (IllegalArgumentException iae) {
					logPane.println("Invalid config: " + iae.getMessage());
				} catch (SQLException se) {
					logPane.println("Error connecting to database: " + se.getMessage());
				}
			}
		});

		disconnectMenuItem = new JMenuItem("Disconnect", KeyEvent.VK_O);
		disconnectMenuItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				try {
					if (conn.isOnline()) {
						conn.disconnect();
						logPane.println("Disconnected");
					}
				} catch (SQLException se) {
					logPane.println("Error disconnecting from database: " + se.getMessage());
				}
			}
		});

		configMenuItem = new JMenuItem("Config", KeyEvent.VK_F);
		configMenuItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				SwingUtilities.invokeLater(new Runnable() {
					@Override
					public void run() {
						ConfigDialog configDialog = new ConfigDialog(mainFrame, config);
						configDialog.show();
					}
				});
			}
		});
		config.readConfig();

		exitMenuItem = new JMenuItem("Exit", KeyEvent.VK_X);
		exitMenuItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				close();
			}
		});

		mainMenu = new JMenu("Menu");
		mainMenu.setMnemonic(KeyEvent.VK_M);
		mainMenu.add(connectMenuItem);
		mainMenu.add(disconnectMenuItem);
		mainMenu.add(configMenuItem);
		mainMenu.add(exitMenuItem);

		menuBar = new JMenuBar();
		menuBar.add(mainMenu);

		tabbedPane = new JTabbedPane();
		tabbedPane.add("Main", syboscPane);
		tabbedPane.add("Log", logPane);

		mainPane = new JPanel(new BorderLayout());
		mainPane.setPreferredSize(new Dimension(1200, 900)); //TODO: remove/fix
		mainPane.add(menuBar, BorderLayout.PAGE_START);
		mainPane.add(tabbedPane, BorderLayout.CENTER);
		mainPane.add(statusBarPane, BorderLayout.PAGE_END);

		mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		mainFrame.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				close();
			}
		});

		mainFrame.add(mainPane);
		mainFrame.pack();
		mainFrame.setLocationRelativeTo(null);
	}

	public void run() {
		mainFrame.setVisible(true);
	}

	private void close() {
		config.writeConfig();
		System.exit(0);
	}

	public static void main(String[] args) {
		SwingUtilities.invokeLater(new Runnable() {
			@Override
			public void run() {
				new Sybosc().run();
			}
		});
	}
}
